package com.bdd.service.Impl;

import com.bdd.entity.Category;
import com.bdd.entity.OrderItem;
import com.bdd.mapper.CategoryDao;
import com.bdd.mapper.OrderItemDao;
import com.bdd.model.bo.CategoryBO;
import com.bdd.model.bo.CategoryMonthSalesAmountBO;
import com.bdd.model.bo.CategorySalesAmountBO;
import com.bdd.model.bo.CategorySalesVolumeBO;
import com.bdd.service.CategoryService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import util.TimeSplitUtil;

import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    CategoryDao categoryDao;

    @Autowired
    OrderItemDao orderItemDao;

    @Override
    public List<CategoryBO> list() {
        List<Category> categoryList = categoryDao.selectAll();
        List<CategoryBO> categoryBOList = CategoryMapUtil.dolisttobolist(categoryList);
        return categoryBOList;
    }

    @Override
    public void add(CategoryBO bo) {
        categoryDao.insertSelectiveBO(bo);
    }

    @Override
    public void edit(CategoryBO bo) {
        Category category = CategoryMapUtil.boToDo(bo);
        categoryDao.updateByPrimaryKeySelective(category);
    }

    @Override
    public void delete(Integer id) {
        categoryDao.deleteByPrimaryKey(id);
    }

    @Override
    public List<CategoryBO> searchByName(String name) {
        List<Category> categoryList = categoryDao.searchByName(name);
        List<CategoryBO> bOtList = CategoryMapUtil.dolisttobolist(categoryList);
        return bOtList;
    }

    @Override
    public List<CategorySalesAmountBO> getSalesAmountGroupByCate() {
        List<CategorySalesAmountBO> categorySalesAmountBOList = categoryDao.selectSalesAmountGroupByCate();
        return categorySalesAmountBOList;
    }

    @Override
    public List<CategorySalesVolumeBO> getSalesVolumeGroupByCate() {
        List<CategorySalesVolumeBO> categorySalesVolumeBOList = categoryDao.getSalesVolumeGroupByCate();
        return categorySalesVolumeBOList;
    }

    @Override
    public List<CategoryMonthSalesAmountBO> getSalesAmountByMonthtGroupByCate(String year, String month) {
        //获取已支付订单中的产品分类
        List<Category> cateList = categoryDao.selectAll();

        //获取当月的第一天和最后一天
        LocalDate date = LocalDate.of(Integer.parseInt(year), Integer.parseInt(month), 1);
        LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
        int monthDays = lastDay.getDayOfMonth() - firstDay.getDayOfMonth() + 1;
        long firstDayTimeStamp = firstDay.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
        long lastDayTimeStamp = lastDay.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();


        //获取某个分类某个周的销售额
        List<CategoryMonthSalesAmountBO> categoryMonthSalesAmountBOList = new LinkedList<>();
        String[] dayInMonth = new String[monthDays];
        for (int i = 0; i < monthDays; i++) {
            dayInMonth[i] = Integer.valueOf(i + 1).toString();
        }

        for (Category cate : cateList) {
            //按月和分类筛选已支付的订单
            List<OrderItem> orderItemListInMonth = orderItemDao.selectByMonth(month, cate.getId());

            //本月没有订单
            if (ObjectUtils.isEmpty(orderItemListInMonth)) {
                Double[] amount = new Double[monthDays];
                Arrays.fill(amount, 0d);
                CategoryMonthSalesAmountBO categoryMonthSalesAmountBO = CategoryMonthSalesAmountBO.builder()
                        .cateName(cate.getName())
                        .lineChartXData(dayInMonth)
                        .lineChartData(amount)
                        .build();
                categoryMonthSalesAmountBOList.add(categoryMonthSalesAmountBO);
                continue;
            }

            //本月有订单
            CategoryMonthSalesAmountBO categoryMonthSalesAmountBO = CategoryMonthSalesAmountBO.builder()
                    .cateName(cate.getName())
                    .lineChartXData(dayInMonth)
                    .build();

            //将订单按每天的销售额进行统计
            int day = 1;
            LinkedList<Double> sumData = new LinkedList<>();
            while (day <= monthDays) {
                double sum = 0;
                for (OrderItem orderItem : orderItemListInMonth) {
                    LocalDate dayStart = LocalDate.of(Integer.parseInt(year), Integer.parseInt(month), day);
                    LocalDate dayEnd = null;
                    if (day < monthDays) {
                        dayEnd = LocalDate.of(Integer.parseInt(year), Integer.parseInt(month), day + 1);
                    } else {
                        dayEnd = LocalDate.of(Integer.parseInt(year), Integer.parseInt(month) + 1, 1);
                    }
                    long dayStartTimeStamp = dayStart.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
                    long dayEndTimeStamp = dayEnd.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();

                    Long orderItemTime = orderItem.getCreateTime().getTime();

                    if (dayStartTimeStamp <= orderItemTime && orderItemTime < dayEndTimeStamp) {
                        sum += orderItem.getPurchasePrice();
                    }
                }
                sumData.add(sum);
                day++;
            }

            categoryMonthSalesAmountBO.setLineChartData(sumData.toArray(new Double[0]));
            categoryMonthSalesAmountBOList.add(categoryMonthSalesAmountBO);
        }

        Double[] cateAmounSum = new Double[monthDays];
        Arrays.fill(cateAmounSum,0d);
        for (int i = 0; i < monthDays; i++) {
            for (CategoryMonthSalesAmountBO bo : categoryMonthSalesAmountBOList) {
                Double[] cateAmount = bo.getLineChartData();
                cateAmounSum[i] += cateAmount[i];
            }
        }
        CategoryMonthSalesAmountBO categoryMonthSalesAmountBO = CategoryMonthSalesAmountBO
                .builder()
                .cateName("总量")
                .lineChartXData(dayInMonth)
                .lineChartData(cateAmounSum)
                .build();
        categoryMonthSalesAmountBOList.add(categoryMonthSalesAmountBO);

        return categoryMonthSalesAmountBOList;
    }

    static class CategoryMapUtil {

        static List<CategoryBO> dolisttobolist(List<Category> categoryList) {
            List<CategoryBO> bOtList = categoryList.stream().map(category -> {
                CategoryBO bo = CategoryBO.builder()
                        .id(category.getId())
                        .name(category.getName())
                        .build();
                return bo;
            }).collect(Collectors.toList());
            return bOtList;
        }

        static Category boToDo(CategoryBO bo) {
            Category category = Category.builder()
                    .id(bo.getId())
                    .name(bo.getName())
                    .build();
            return category;
        }

    }
}
